#include <iostream>
#include <fstream>
#include <sstream>
#include "json/json.h"
class Configuration{
public:
    static Configuration &GetInstance(){
        static Configuration instance;
        return instance;
    }
    bool LoadConfig() {
        if(load_state_){
            return true;
        }
        std::string config_filename("");
        auto config_path = getenv("CONFIG_PATH");
        if(config_path != nullptr){
            config_filename = config_path + CONFIG_FILE_NAME;
            std::cout<<"LoadConfig, file path: " <<config_filename<<std::endl;
        } else {
           std::cout<<"LoadConfig, no file path: " <<config_filename<<std::endl; 
           return false;     
        }
        std::ifstream ifs;
        ifs.open(config_filename);
        if(!ifs.is_open()){
            return false;
        }
        std::stringstream ss;
        ss << ifs.rdbuf();
        ifs.close();
        std::string result = ss.str();
        const std::string rawJson = ss.str();;
        const auto rawJsonLength = static_cast<int>(rawJson.length());
        constexpr bool shouldUseOldWay = false;
        JSONCPP_STRING err;
        Json::Value root;

        if (shouldUseOldWay) {
            Json::Reader reader;
            reader.parse(rawJson, root);
        } else {
            Json::CharReaderBuilder builder;
            const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
            if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
                            &err)) {
            std::cout << "error" << std::endl;
            return EXIT_FAILURE;
            }
        }
        SetConfigValue(root);
        load_state_ = true;
        return true;
    }
    void SetConfigValue(Json::Value &root){
        configure_a_ = root["CONFIGURATION_A_PATH"].asString();
        configure_b_ = root["CONFIGURATION_B_PATH"].asString();
        configure_c_ = root["CONFIGURATION_C_PATH"].asString();
        configure_d_ = root["CONFIGURATION_D_PATH"].asString();
        configure_e_ = root["CONFIGURATION_E_PATH"].asString();
        configure_f_ = root["CONFIGURATION_F_PATH"].asString();
    }
private:
    Configuration()
        :configure_a_("")
        ,configure_b_("")
        ,configure_c_("")
        ,configure_d_("")
        ,configure_e_("")
        ,configure_f_(""){
    }

private:
    std::string configure_a_;
    std::string configure_b_;
    std::string configure_c_;
    std::string configure_d_;
    std::string configure_e_;
    std::string configure_f_;

    bool load_state_;

    const std::string CONFIG_FILE_NAME = "configuration.json";
};